/**
 * 
 */
package com.ydy.service.order.impl;

import static com.ydy.utils.BigDecimalUtil.add;
import static com.ydy.utils.BigDecimalUtil.div2bit;
import static com.ydy.utils.BigDecimalUtil.mul;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.ydy.constant.OrderStatusEnum;
import com.ydy.constant.SystemConstant;
import com.ydy.dto.BillDTO;
import com.ydy.exception.BusinessException;
import com.ydy.exception.DataNotFoundException;
import com.ydy.exception.ValidateException;
import com.ydy.ienum.EnumGood;
import com.ydy.ienum.EnumOrder;
import com.ydy.ienum.EnumSystem;
import com.ydy.mapper.BookMapper;
import com.ydy.mapper.OrderItemMapper;
import com.ydy.mapper.OrderMapper;
import com.ydy.mapper.OrderStatusMapper;
import com.ydy.mapper.SkuMapper;
import com.ydy.mapper.SpuMapper;
import com.ydy.model.Book;
import com.ydy.model.Order;
import com.ydy.model.OrderItem;
import com.ydy.model.OrderStatus;
import com.ydy.model.Sku;
import com.ydy.model.Spu;
import com.ydy.model.Staff;
import com.ydy.model.User;
import com.ydy.service.book.BookService;
import com.ydy.service.order.OrderService;
import com.ydy.utils.DateUtil;
import com.ydy.utils.ValidateUtil;
import com.ydy.vo.other.BaseVo;
import com.ydy.vo.other.PageVo;
import com.ydy.vo.other.ResultVo;

/**
 * @author xuzhaojie
 *
 *         2019年5月27日 下午3:52:15
 */
@Service
@Transactional
public class OrderServiceImpl implements OrderService {
	private final static Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);
	@Autowired
	private OrderMapper orderMapper;
	@Autowired
	private OrderStatusMapper orderStatusMapper;
	@Autowired
	private OrderItemMapper orderItemMapper;
	@Autowired
	private SkuMapper skuMapper;
	@Autowired
	private SpuMapper spuMapper;
	@Autowired
	private BookService bookService;
	@Autowired
	private BookMapper bookMapper;

	@Value("${NOT_PAY_TIME_LONG}")
	private String NOT_PAY_TIME_LONG;
	private Long timeLong = null;
	private static Long lastOrderId = null;
	private static Object lock = new Object();

	@Override
	public PageVo<Order> select(Order order, Staff staff, String word, Date startTime, Date endTime, Integer page,
			Integer size) {
		PageVo<Order> vo = new PageVo<Order>(page, size);
		Page<Order> pageBean = PageHelper.startPage(vo.getPage(), vo.getSize(), "order_id desc");
		List<Order> list = orderMapper.selectData(word, staff.getShopId(), null, order.getOrderId(),
				order.getReceiver(), order.getPhone(), order.getEmail(), order.getStatus(), startTime, endTime);
		Book book = null;
		for (Order o : list) {
			o.setId(o.getOrderId().toString());
			book = bookMapper.selectByPrimaryKey(o.getOrderId());
			o.setBook(book);
			if (OrderStatusEnum.COMMIT.getCode().equals(o.getStatus())) {
				o.setCloseTime(new Date(o.getCreateTime().getTime() + getTimeLong()));
			}
		}
		vo.setTotal(pageBean.getTotal());
		vo.setList(list);
		return vo;
	}

	@Override
	public PageVo<Order> selectUserOrder(Order order, User user, String word, Date startTime, Date endTime,
			Integer page, Integer size) {
		PageVo<Order> vo = new PageVo<Order>(page, size);
		Page<Order> pageBean = PageHelper.startPage(vo.getPage(), vo.getSize(), "order_id desc");
		List<Order> list = orderMapper.selectData(word, null, user.getId(), order.getOrderId(), order.getReceiver(),
				order.getPhone(), order.getEmail(), order.getStatus(), startTime, endTime);
		Book book = null;
		for (Order o : list) {
			o.setId(o.getOrderId().toString());
			book = bookMapper.selectByPrimaryKey(o.getOrderId());
			o.setBook(book);
			if (OrderStatusEnum.COMMIT.getCode().equals(o.getStatus())) {
				o.setCloseTime(new Date(o.getCreateTime().getTime() + getTimeLong()));
			}
		}
		vo.setTotal(pageBean.getTotal());
		vo.setList(list);
		return vo;
	}

	private Long getTimeLong() {
		if (timeLong == null) {
			Long time = DateUtil.formatTimeLong(NOT_PAY_TIME_LONG);
			timeLong = time;
		}
		return timeLong;
	}

	@Override
	public Long createOrderId() {
		Long nowOrderId = null;
		synchronized (lock) {
			// 客户要求这样的生产订单模式
			nowOrderId = Long.parseLong(DateUtil.produceId());
			if (lastOrderId != null && nowOrderId.equals(lastOrderId)) {
				nowOrderId++;
				lastOrderId = nowOrderId;
			}
		}
		return nowOrderId;
	}

	@Override
	public BillDTO calculateBill(BillDTO bill) {
		// 校验数据有效
		Map<String, String> validateInfo = ValidateUtil.validateEntity(bill);
		if (!validateInfo.isEmpty()) {
			throw new ValidateException(validateInfo);
		}
		List<OrderItem> items = bill.getItems();
		for (OrderItem dto : items) {
			validateInfo = ValidateUtil.validateEntity(dto);
			if (!validateInfo.isEmpty()) {
				throw new ValidateException(validateInfo);
			}
		}
		return calculate(bill);
	}

	private BillDTO calculate(BillDTO bill) {
		if (bill == null) {
			throw new NullPointerException();
		}
		BigDecimal totalPay = new BigDecimal(0.0);// 总金额
		BigDecimal actualPay = new BigDecimal(0.0);// 实付金额
		// TODO 计算邮费
		bill.setPostFee(0L);// 默认包邮
		totalPay = add(totalPay, new BigDecimal(bill.getPostFee()));// 邮费
		actualPay = add(actualPay, new BigDecimal(bill.getPostFee()));// 邮费
		Sku sku = null;
		Spu spu = null;
		for (OrderItem item : bill.getItems()) {
			sku = skuMapper.selectByPrimaryKey(item.getSkuId());
			if (sku == null || SystemConstant.GOOD_OFF.equals(sku.getSkuStatus())) {
				log.error("Sku未上架或不存在：" + item.getSkuId());
				throw new BusinessException(EnumGood.SKU_OFF);
			}
			if (!sku.getShopId().equals(bill.getShopId())) {
				throw new BusinessException(EnumOrder.ORDER_MUST_ONE_SHOP);
			}
			spu = spuMapper.selectByPrimaryKey(sku.getSpuId());
			if (spu == null || SystemConstant.GOOD_OFF.equals(spu.getSpuStatus())) {
				log.error("Spu未上架或不存在：" + sku.getSpuId());
				throw new BusinessException(EnumGood.SPU_OFF);
			}
			item.setPrice(sku.getNowPrice());
			BigDecimal itemActualTotal = mul(new BigDecimal(sku.getNowPrice()), new BigDecimal(item.getNum()));// item的实付金额
			BigDecimal itemTotal = mul(new BigDecimal(sku.getPrice()), new BigDecimal(item.getNum()));// item的总金额
			// 设置item的字段
			item.setImage(sku.getMainImage());// 设置主图
			item.setName(spu.getName() + "(" + sku.getName() + ")");
			item.setTotalPrice(itemActualTotal.doubleValue());
			actualPay = add(actualPay, itemActualTotal);// 汇总实付金额
			totalPay = add(totalPay, itemTotal);// 汇总总金额
		}
		actualPay = div2bit(actualPay, new BigDecimal(1.0));
		totalPay = div2bit(totalPay, new BigDecimal(1.0));
		bill.setActualPay(actualPay.doubleValue());// 设置实付金额
		bill.setTotalPay(totalPay.doubleValue());// 设置总金额
		bill.setCoinType(SystemConstant.LOCAL_COIN_TYPE);// 设置本地币种
		return bill;
	}

	@Override
	public Order createOrder(Order order, User user) {
		// 校验数据有效
		order.setUserId(user.getId());
		Map<String, String> validateInfo = ValidateUtil.validateEntity(order);
		if (!validateInfo.isEmpty()) {
			throw new ValidateException(validateInfo);
		}
		Date now = new Date();
		Long orderId = createOrderId();// 创建订单ID
		// 计算账单
		BillDTO billDTO = calculateBill(order);
		List<OrderItem> itemList = billDTO.getItems();
		String orderName = "Order";
		for (OrderItem orderItem : itemList) {// 设置orderItem
			orderItem.setOrderId(orderId);
			orderName = orderItem.getName();
		}
		// 构建订单属性,订单条目,订单状态属性开始
		order.setOrderId(orderId);
		order.setName(orderName);
		order.setId(orderId.toString());
		order.setCreateTime(now);
		order.setItemSize(itemList.size());
		orderMapper.insertSelective(order);
		orderItemMapper.insertList(itemList);
		order.setItems(itemList);
		OrderStatus status = new OrderStatus();
		status.setOrderStatus(OrderStatusEnum.COMMIT.getCode());
		status.setOrderId(orderId);
		status.setCreateTime(now);
		orderStatusMapper.insertSelective(status);
		order.setStatus(status.getOrderStatus());
		Book book = order.getBook();
		book.setOrderId(orderId);
		book.setId(orderId);// ID用同样的ORDERid
		book.setShopId(order.getShopId());
		bookService.save(book, user);
		log.info("创建订单成功:" + orderId);
		// 构建订单属性,订单条目,订单状态属性结束
		return order;
	}

	@Override
	public BaseVo updateOrderStatusPay(Long orderId, Date date) {
		OrderStatus status = new OrderStatus();
		status.setOrderId(orderId);
		if (date == null) {
			date = new Date();
		}
		status.setOrderStatus(OrderStatusEnum.PAY.getCode());
		status.setPaymentTime(date);
		orderStatusMapper.updateByPrimaryKeySelective(status);
		log.info("订单支付成功:" + orderId);
		return new ResultVo(EnumSystem.SUSS);
	}

	@Override
	public BaseVo updateOrderStatusRefund(Long orderId, Date date) {
		OrderStatus status = new OrderStatus();
		status.setOrderId(orderId);
		if (date == null) {
			date = new Date();
		}
		status.setOrderStatus(OrderStatusEnum.REFUND.getCode());
		status.setRefundTime(date);
		orderStatusMapper.updateByPrimaryKeySelective(status);
		bookService.delete(orderId, null);
		log.info("订单退款成功:" + orderId);
		return new ResultVo(EnumSystem.SUSS);
	}

	@Override
	public BaseVo updateOrderStatusClose(Long orderId, User user) {
		OrderStatus status = createOrderStatus(orderId, OrderStatusEnum.CLOSED);
		orderStatusMapper.updateByPrimaryKeySelective(status);
		bookService.delete(orderId, user);
		log.info("订单取消成功:" + orderId);
		return new ResultVo(EnumSystem.SUSS);
	}

	private OrderStatus createOrderStatus(Long orderId, OrderStatusEnum statusEnum) {
		OrderStatus temp = orderStatusMapper.selectByPrimaryKey(orderId);
		if (temp == null) {
			log.info("找不到订单信息:" + orderId);
			throw new DataNotFoundException(EnumOrder.ORDER_NOT_FOUND);
		}
		OrderStatus status = new OrderStatus();
		status.setOrderId(orderId);
		status.setOrderStatus(statusEnum.getCode());
		Date now = new Date();
		if (OrderStatusEnum.CLOSED.equals(statusEnum)) {
			status.setCloseTime(now);
		} else if (OrderStatusEnum.PAY.equals(statusEnum)) {
			status.setPaymentTime(now);
		} else if (OrderStatusEnum.FINISH.equals(statusEnum)) {
			status.setFinishTime(now);
		} else if (OrderStatusEnum.REFUND.equals(statusEnum)) {
			status.setRefundTime(now);
		} else {
			log.error("未知的订单状态");
			throw new BusinessException(EnumOrder.UNKNOW_ORDER_STATUS);
		}
		return status;
	}

	@Override
	public BaseVo delete(Long id) {
		return null;
	}

	@Override
	public Order selectById(Long id, Staff staff) {
		if (id == null) {
			throw new NullPointerException();
		}
		Order order = orderMapper.selectByPrimaryKey(id);
		if (order == null) {
			log.info("找不到订单信息:" + id);
			throw new DataNotFoundException(EnumOrder.ORDER_NOT_FOUND);
		}
		if (!order.getShopId().equals(staff.getShopId())) {
			throw new DataNotFoundException(EnumOrder.ORDER_SHOP_NOT_FIT);
		}
		OrderStatus status = orderStatusMapper.selectByPrimaryKey(order.getOrderId());
		if (status == null) {
			log.info("找不到订单状态信息:" + id);
			throw new DataNotFoundException(EnumOrder.ORDER_STATUS_NOT_FOUND);
		}
		order.setOrderStatus(status);
		order.setStatus(status.getOrderStatus());
		OrderItem orderItem = new OrderItem();
		orderItem.setOrderId(order.getOrderId());
		List<OrderItem> list = orderItemMapper.select(orderItem);
		order.setItems(list);
		return order;
	}

	@Override
	public Order selectByIdAndUser(Long id, User user) {
		if (id == null) {
			throw new NullPointerException();
		}
		Order order = orderMapper.selectByPrimaryKey(id);
		if (order == null) {
			log.info("找不到订单信息:" + id);
			throw new DataNotFoundException(EnumOrder.ORDER_NOT_FOUND);
		}
		if (!order.getUserId().equals(user.getId())) {
			throw new BusinessException(EnumOrder.ORDER_NOT_FIT_USER);
		}
		OrderStatus status = orderStatusMapper.selectByPrimaryKey(order.getOrderId());
		if (status == null) {
			log.info("找不到状态信息:" + id);
			throw new DataNotFoundException(EnumOrder.ORDER_STATUS_NOT_FOUND);
		}
		order.setId(id.toString());
		order.setOrderStatus(status);
		order.setStatus(status.getOrderStatus());
		OrderItem item = new OrderItem();
		item.setOrderId(order.getOrderId());
		List<OrderItem> list = orderItemMapper.select(item);
		order.setItems(list);
		return order;
	}

	@Override
	public Order selectOrderAndStatusByIdAndUser(Long id, User user) {
		if (id == null) {
			throw new NullPointerException();
		}
		Order order = orderMapper.selectByPrimaryKey(id);
		if (order == null) {
			log.info("找不到订单信息:" + id);
			throw new DataNotFoundException(EnumOrder.ORDER_NOT_FOUND);
		}
		if (user != null && !order.getUserId().equals(user.getId())) {
			throw new BusinessException(EnumOrder.ORDER_NOT_FIT_USER);
		}
		OrderStatus status = orderStatusMapper.selectByPrimaryKey(order.getOrderId());
		if (status == null) {
			log.info("找不到状态信息:" + id);
			throw new DataNotFoundException(EnumOrder.ORDER_STATUS_NOT_FOUND);
		}
		order.setId(id.toString());
		order.setOrderStatus(status);
		order.setStatus(status.getOrderStatus());
		return order;
	}

	@Override
	public List<OrderStatus> selectOrderCommit(OrderStatusEnum orderStatusEnum, Date createTime) {
		return orderStatusMapper.selectStatusCommit(orderStatusEnum.getCode(), createTime, null);
	}

}
